#include "uint16.h"
#include "alloc.h"
#include "str.h"
#include <string.h>
#include <stdlib.h>
#include "ip4.h"
#include "open.h"
#include "tai.h"
#include "cdb.h"
#include "byte.h"
#include "case.h"
#include "dns.h"
#include "seek.h"
#include "response.h"
#include "ipdb.h"
#include "env.h"
#include "scan.h"
#include "prot.h"
#include "strerr.h"
#include "stralloc.h"
#include "qlog.h"

#define FATAL "ipdbops: fatal: "



int ipdb_key_from_uint (stralloc *key, unsigned int ipuint,unsigned char mask, char *uid, int ulen, int applymask)
{
	char ch;
	char x[255];
	int i;
	unsigned int netmask = 0;
	if (!stralloc_copyb(key,"\0%",2)) strerr_die1sys(111,FATAL);;
	if (applymask) {
		for (i = 0; i < mask; i++) netmask |= 1 << (31 - i);
		ipuint = ipuint & netmask;
	}
#ifdef IPDB_DEBUG
	byte_copy(x,ulen,uid);
	x[ulen] = '\0';
	fprintf(stderr,"usekey %u.%u.%u.%u/%u/%s\n", (ipuint>>24)&0xff,(ipuint>>16)&0xff,(ipuint>>8)&0xff,ipuint&0xff,mask,x);
#endif
	ch = (ipuint >> 24) & 0xff; if (!stralloc_catb(key,&ch,1)) strerr_die1sys(111,FATAL);;
	ch = (ipuint >> 16) & 0xff; if (!stralloc_catb(key,&ch,1)) strerr_die1sys(111,FATAL);;
	ch = (ipuint >> 8) & 0xff; if (!stralloc_catb(key,&ch,1)) strerr_die1sys(111,FATAL);;
	ch = ipuint  & 0xff; if (!stralloc_catb(key,&ch,1)) strerr_die1sys(111,FATAL);;
	if (!stralloc_catb(key,&mask,1)) strerr_die1sys(111,FATAL);;
	if (uid ) {
		if (!stralloc_catb(key,uid,ulen)) strerr_die1sys(111,FATAL);;
	}
	return 1;
}

int ipdb_key_from_str (stralloc *key, const char *ipstr, unsigned char mask, char *uid, int ulen, int applymask)
{
	unsigned char ip[4];
	unsigned int j;
	ip4_scan(ipstr,ip);
	ip4_num(&j,ip);
	return ipdb_key_from_uint(key,j,mask,uid,ulen,applymask);
}

int ipdb_key_from_bytes (stralloc *key, unsigned char ip[4],unsigned char mask, char *uid, int ulen, int applymask)
{
	unsigned int j;
	ip4_num(&j,ip);
	return ipdb_key_from_uint(key, j,mask,uid,ulen,applymask);
}


void ipdb_make_key(unsigned char ip[4],unsigned char mask,char *key)
{
	register unsigned char i;
	unsigned int j = 0;
	unsigned int netmask = 0;
	for (i = 0; i < mask; i++) {
		netmask |= 1 << (31 - i);
	}
	ip4_num(&j,ip);
	j = j & netmask;
	key[0] = 0;
	key[1] = '%';
	key[2] = (j>>24)&0xff;
	key[3] = (j>>16)&0xff;
	key[4] = (j>>8)&0xff;
	key[5] = j&0xff;
	key[6] = mask;
#ifdef IPDB_DEBUG
	fprintf(stderr,"trykey %u.%u.%u.%u/%u\n", (j>>24)&0xff,(j>>16)&0xff,(j>>8)&0xff,j&0xff,mask);
#endif
}

int ipdb_get (struct cdb *c, unsigned char ip[4], char *uid, int ulen, char *cc)
{
	stralloc key;
	unsigned char intmask;
	int r = -1;

	key.s = NULL;
	key.len = 0;
	for(intmask = 32; intmask >=1 ; intmask--) {
		ipdb_key_from_bytes(&key,ip,intmask,uid, ulen,1);
		r = cdb_find(c,key.s,key.len);
		if (r) break;
	}
	if (r == -1) return 0;

	if (r && (cdb_datalen(c) == 2)) {
		if (cdb_read(c,cc,2,cdb_datapos(c)) == -1) return 0;
	}
	return 1;
}

